package com.mvc.framework.service;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;

import com.mvc.framework.model.Auditable;
import com.mvc.framework.model.Tree;
@Service
public class TreeManager extends BaseService<Tree, Integer>{
	
	public void save(Tree tree) {
		if(tree.getParentId()!=null&&tree.getParentId()!=-1){
			Tree parent = getByObjectId(tree.getParentId());
			if(parent.getIsLeaf()==Tree.IS_LEAF){
				parent.setIsLeaf(Tree.IS_NOT_LEAF);
				super.save(parent);
			}
			tree.setLevelDeep(parent.getLevelDeep() + Tree.DEFAULT_DEEP_LEVEL_STEP);
		} else {
			tree.setLevelDeep(Tree.DEFAULT_DEEP_LEVEL);
		}
		if(tree.getObjectId()==null){
			tree.setIsLeaf(Tree.IS_LEAF);
		}else{
			int childCount = getChildrenCount(tree.getObjectId());
			if(childCount==0){
				tree.setIsLeaf(Tree.IS_LEAF);
			}else{
				tree.setIsLeaf(Tree.IS_NOT_LEAF);
			}
		}
		if(tree.getOrderId()==null){
			if(tree.getParentId()!=null){
				tree.setOrderId(getChildrenMaxOrderId(tree.getParentId()) + 1);
			}else{
				tree.setOrderId(Tree.DEFAULT_ORDER_ID);
			}
		}
		super.save(tree);
	}
	
	public int getChildrenCount(int parentId){
		String sql = "select COUNT(*) from " + Tree.class.getName() + " A where A.recStatus = " 
	                 + Auditable.REC_STATUS_VALID + " AND parentId = " + parentId ;
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery(sql);
		Object object = query.list().get(0);
		int count = object==null?0:((Number)object).intValue(); 
		session.close();
		return count;
	}
	/**
	 * Query all child nodes
	 * @param code
	 * @return
	 */
	public List<Tree> getRecursionChildrenByCode(String code){
		if(StringUtils.isNotBlank(code)){
			String sql="select A from "+ Tree.class.getName() + " A where A.codeNo like '" + code + "%' and A.recStatus= " + Auditable.REC_STATUS_VALID + " order by levelDeep,orderId";
			return searchBySql(sql);
		}else {
			return getAll();
		}
	}
	/**
	 * Query the direct child node
	 * @param code
	 * @return
	 */
	public List<Tree> getChildrenByCode(String code){
		String sql="select A from "+ Tree.class.getName() + " A," + Tree.class.getName() + " B where A.parentId = B.objectId " 
					+ " and A.recStatus=" + Auditable.REC_STATUS_VALID +" AND B.recStatus = " + Auditable.REC_STATUS_VALID 
					+ " and B.codeNo = '" + code +"' order by A.orderId";
		return searchBySql(sql);
	}
	
	public List<Tree> getAll(){
		return searchBySql("select A from " + Tree.class.getName() + " A where recStatus= " + Auditable.REC_STATUS_VALID 
				+ " order by levelDeep,orderId");
	}
	
	public Tree getTreeByCode(String codeNo){
		if(null!=codeNo){
			String sql="select A from " + Tree.class.getName() + " A where A.codeNo = '" + codeNo + "' and  recStatus=" 
					+ Auditable.REC_STATUS_VALID;
			List<Tree> list=searchBySql( sql);
			return list.get(0);
		}
		return null;
	}
	
	public List<Tree> getChildren(int parentId) {
		return searchBySql("select A from " + Tree.class.getName()
				+ " A where A.parentId =" + parentId + " and recStatus = " + Auditable.REC_STATUS_VALID + " order by orderId");
	}
	
	public int getChildrenMaxOrderId(int parentId){
		String sql = "select max(orderId) from " + Tree.class.getName() + " A where A.recStatus = " 
	                 + Auditable.REC_STATUS_VALID + " AND parentId = " + parentId ;
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		Query query = session.createQuery(sql);
		Object object = query.list().get(0);
		int count = object==null?0:((Number)object).intValue(); 
		session.close();
		return count;
	}
}
